package hbbft

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"sync"
	"time"
)

// LogLevel 日志级别
type LogLevel int

const (
	DEBUG LogLevel = iota
	INFO
	WARN
	ERROR
)

// LogEntry 日志条目
type LogEntry struct {
	Timestamp time.Time   `json:"timestamp"`
	Level     LogLevel    `json:"level"`
	NodeID    uint64      `json:"node_id"`
	Component string      `json:"component"`
	Message   string      `json:"message"`
	Data      interface{} `json:"data,omitempty"`
}

// Logger 结构化日志器
type Logger struct {
	nodeID    uint64
	level     LogLevel
	logFile   *os.File
	mu        sync.Mutex
	component string
}

// NewLogger 创建新的日志器
func NewLogger(nodeID uint64, component string, level LogLevel) *Logger {
	// 确保logs目录存在
	logDir := "logs"
	if err := os.MkdirAll(logDir, 0755); err != nil {
		fmt.Printf("Failed to create logs directory: %v\n", err)
		// 即使目录创建失败，也返回一个基本的logger
		return &Logger{
			nodeID:    nodeID,
			level:     level,
			logFile:   nil,
			component: component,
		}
	}
	
	// 创建日志文件
	logFile, err := os.OpenFile(
		filepath.Join(logDir, fmt.Sprintf("node_%d_%s.log", nodeID, component)),
		os.O_CREATE|os.O_WRONLY|os.O_APPEND,
		0644,
	)
	if err != nil {
		fmt.Printf("Failed to create log file: %v\n", err)
		// 即使文件创建失败，也返回一个基本的logger
		return &Logger{
			nodeID:    nodeID,
			level:     level,
			logFile:   nil,
			component: component,
		}
	}
	
	return &Logger{
		nodeID:    nodeID,
		level:     level,
		logFile:   logFile,
		component: component,
	}
}

// log 内部日志方法
func (l *Logger) log(level LogLevel, message string, data interface{}) {
	if level < l.level {
		return
	}
	
	entry := LogEntry{
		Timestamp: time.Now(),
		Level:     level,
		NodeID:    l.nodeID,
		Component: l.component,
		Message:   message,
		Data:      data,
	}
	
	l.mu.Lock()
	defer l.mu.Unlock()
	
	// 输出到文件
	if l.logFile != nil {
		jsonData, err := json.Marshal(entry)
		if err == nil {
			l.logFile.WriteString(string(jsonData) + "\n")
			l.logFile.Sync()
		}
	}
	
	// 输出到控制台
	levelStr := l.getLevelString(level)
	fmt.Printf("[%s] Node %d %s: %s", 
		levelStr, l.nodeID, l.component, message)
	if data != nil {
		fmt.Printf(" | Data: %+v", data)
	}
	fmt.Println()
}

func (l *Logger) getLevelString(level LogLevel) string {
	switch level {
	case DEBUG:
		return "DEBUG"
	case INFO:
		return "INFO"
	case WARN:
		return "WARN"
	case ERROR:
		return "ERROR"
	default:
		return "UNKNOWN"
	}
}

// Debug 调试日志
func (l *Logger) Debug(message string, data ...interface{}) {
	var dataInterface interface{}
	if len(data) > 0 {
		dataInterface = data[0]
	}
	l.log(DEBUG, message, dataInterface)
}

// Info 信息日志
func (l *Logger) Info(message string, data ...interface{}) {
	var dataInterface interface{}
	if len(data) > 0 {
		dataInterface = data[0]
	}
	l.log(INFO, message, dataInterface)
}

// Warn 警告日志
func (l *Logger) Warn(message string, data ...interface{}) {
	var dataInterface interface{}
	if len(data) > 0 {
		dataInterface = data[0]
	}
	l.log(WARN, message, dataInterface)
}

// Error 错误日志
func (l *Logger) Error(message string, data ...interface{}) {
	var dataInterface interface{}
	if len(data) > 0 {
		dataInterface = data[0]
	}
	l.log(ERROR, message, dataInterface)
}

// Close 关闭日志器
func (l *Logger) Close() error {
	l.mu.Lock()
	defer l.mu.Unlock()
	
	if l.logFile != nil {
		return l.logFile.Close()
	}
	return nil
}

// LogEpochCompletion 记录epoch完成
func (l *Logger) LogEpochCompletion(epoch uint64, txCount int, duration time.Duration) {
	l.Info("Epoch completed", map[string]interface{}{
		"epoch":     epoch,
		"tx_count":  txCount,
		"duration":  duration.Milliseconds(),
		"tps":       float64(txCount) / duration.Seconds(),
	})
}

// LogComponentLatency 记录组件延迟
func (l *Logger) LogComponentLatency(component string, operation string, latency time.Duration) {
	l.Debug("Component latency", map[string]interface{}{
		"component": component,
		"operation": operation,
		"latency":   latency.Milliseconds(),
	})
}

// LogNetworkMessage 记录网络消息
func (l *Logger) LogNetworkMessage(direction string, to uint64, size int) {
	l.Debug("Network message", map[string]interface{}{
		"direction": direction,
		"to":        to,
		"size":      size,
	})
}

// LogConsensusProgress 记录共识进度
func (l *Logger) LogConsensusProgress(epoch uint64, phase string, details interface{}) {
	l.Info("Consensus progress", map[string]interface{}{
		"epoch":  epoch,
		"phase":  phase,
		"details": details,
	})
}
